package org.nViron.nvOrganism;

//~--- non-JDK imports --------------------------------------------------------

import org.nViron.nvSim.nvObject;

/**
 * Organism is a object implementation that has states of living and some basic update functionality
 * @author Roland Haring <p>
 * <script type="text/javascript" src="http://www.ohloh.net/p/376434/widgets/project_basic_stats.js"></script>
 */
public abstract class nvOrganism extends nvObject {
    private final nvStateMgr stateMgr = new nvStateMgr();
    private int        degeneratingTimeMS;
    private int        sproutingTimeMS;

    public nvOrganism(nvOrganismMgr organismMgr) {
        super(organismMgr);
        sproutingTimeMS    = 2000;
        degeneratingTimeMS = 2000;
    }

    abstract public void degenerate();

    protected boolean doneDegenerating() {
        return getTimeInStateRel() < 1.0f;
    }

    protected boolean doneSprouting() {
        return getTimeInStateRel() < 1.0f;
    }

    protected int getDegeneratingTimeMS() {
        return degeneratingTimeMS;
    }

    public nvOrganismMgr getOrganismMgr() {
        return (nvOrganismMgr) getObjectMgr();
    }

    protected int getSproutingTimeMS() {
        return sproutingTimeMS;
    }

    public int getState() {
        return stateMgr.getState();
    }

    public float getTimeInStateRel() {
        switch (getState()) {
        case nvStateMgr.DEGENERATING :
            return (float) stateMgr.getMsInState() / (float) getDegeneratingTimeMS();

        case nvStateMgr.SPROUTING :
            return (float) stateMgr.getMsInState() / (float) getSproutingTimeMS();

        case nvStateMgr.SPAWN :
        case nvStateMgr.DEAD :
        case nvStateMgr.LIVING :
            break;
        }

        return 0.0f;
    }

    public boolean isRenderable() {
        return (getState() == nvStateMgr.LIVING) || (getState() == nvStateMgr.DEGENERATING)
               || (getState() == nvStateMgr.SPROUTING);
    }

    protected void onStateChange(int state) {

        // overload and do something here if you want to
    }

    protected void setDegeneratingTimeMS(int degeneratingTimeMS) {
        this.degeneratingTimeMS = degeneratingTimeMS;
    }

    protected void setSproutingTimeMS(int sproutingTimeMS) {
        this.sproutingTimeMS = sproutingTimeMS;
    }

    public void setState(int state) {
        if (stateMgr.setState(state)) {
            onStateChange(getState());
        }
    }

    public void update(float timeStep) {
        switch (getState()) {
        case nvStateMgr.SPAWN :
            break;

        case nvStateMgr.DEGENERATING :
            if (doneDegenerating()) {
                setState(nvStateMgr.DEAD);
            }

            break;

        case nvStateMgr.SPROUTING :
            if (doneSprouting()) {
                setState(nvStateMgr.LIVING);
            }

            break;

        case nvStateMgr.DEAD :
            break;

        case nvStateMgr.LIVING :
            break;
        }
    }

    protected void updateStateRelativeToChild(nvOrganism child) {
        switch (getState()) {
        case nvStateMgr.SPAWN :
            break;

        case nvStateMgr.DEGENERATING :
            break;

        case nvStateMgr.SPROUTING :
            break;

        case nvStateMgr.DEAD :
            break;

        case nvStateMgr.LIVING :
            if (child.getState() == nvStateMgr.SPAWN) {
                child.setState(nvStateMgr.SPROUTING);
            } else if (child.getState() == nvStateMgr.DEAD) {
                setState(nvStateMgr.DEGENERATING);
            }

            break;
        }
    }
}



